
package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.druid.util.Utils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.ReservationDto;
import com.zzyl.entity.Member;
import com.zzyl.entity.Reservation;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.CustomerReservationMapper;
import com.zzyl.mapper.MemberMapper;
import com.zzyl.service.CustomerReservationService;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.utils.StringUtils;
import com.zzyl.utils.UserThreadLocal;
import com.zzyl.vo.ReservationCountVo;
import com.zzyl.vo.ReservationVo;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 客户预约服务实现类，提供预约相关的业务逻辑处理。
 */
@Service
public class CustomerReservationServiceImpl implements CustomerReservationService {

    @Autowired
    private CustomerReservationMapper customerReservationMapper;


    /**
     * 用于格式化日期时间的工具。
     */
    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 预约开始时间，从早上8点开始（毫秒数）。
     */
    private static final Long START_TIME = 3600000L * 8;

    /**
     * 预约结束时间，到晚上6点结束（毫秒数）。
     */
    private static final Long END_TIME = 3600000L * 18;

    /**
     * 每个时间段的最大数量限制。
     */
    private static final Integer TIME_LIST_MAX_SIZE = 21;

    /**
     * 每个时间段的最大预约次数。
     */
    private static final Integer RSERVATION_MAX_COUNT = 6;

    /**
     * 查询用户的取消预约数量。
     *
     * @return 用户的取消预约数量
     */
    @Override
    public Integer getCancelledCount() {
        // 获取当前线程中的用户ID
        Long userId = UserThreadLocal.get();

        // 调用Mapper层查询该用户的取消预约次数
        Integer cancelledCount = customerReservationMapper.getCancelledCount(userId);
        return cancelledCount;
    }

    /**
     * 查询每个时间段的剩余预约次数。
     *
     * @param time 基准时间（毫秒数）
     * @return 每个时间段的剩余预约次数列表
     */
    @Override
    public List<ReservationCountVo> getCountByTime(Long time) {
        // 计算预约时间的开始和结束时间
        String startTime = simpleDateFormat.format(time + START_TIME);
        String endTime = simpleDateFormat.format(time + END_TIME);

        // 获取可预约的时间段列表
        List<ReservationCountVo> timeList = getTimeList(time);

        // 查询未报道的预约时间次数
        List<ReservationCountVo> resultList = customerReservationMapper.getCountByTime(startTime, endTime);

        if (ObjectUtil.isEmpty(resultList)) {
            // timeList 为空, 直接返回timeList;
            return timeList;
        }
        // 更新timeList中每个时间段的剩余预约次数
        for (ReservationCountVo reservationCountVo : resultList) {
            LocalDateTime time1 = reservationCountVo.getTime();
            Integer count1 = reservationCountVo.getCount();
            for (ReservationCountVo countVo : timeList) {
                LocalDateTime time2 = countVo.getTime();
                if (ObjectUtils.equals(time1, time2)) {
                    Integer count2 = countVo.getCount();
                    countVo.setCount(count2 - count1);
                }
            }
        }
        return timeList;
    }

    /**
     * 新增预约
     * @param reservationDto
     */
    @Override
    public void save(ReservationDto reservationDto) {
        // 判断内容是否为空
        if (ObjectUtil.isEmpty(reservationDto)) {
            // 预约内容不能为空
            throw new BaseException(BasicEnum.RESERVATION_CONTENT_IS_NULL);
        }

        // 判断手机号格式是否合法
        String reg = ("^((13[0-9])|(14[0|5|6|7|9])|(15[0|1|2|3|5|6|7|8|9])|(16[2|5|6|7])|(17[0|1|2|3|5|6|7|8])|(18[0-9])|(19[0|1|2|3|5|6|7|8|9]))\\d{8}$");

        if (!reservationDto.getMobile().matches(reg)) {
            // 手机号不合法
            throw new BaseException(BasicEnum.PHONE_FORMAT_ERROR);
        }

        // 判断手机号是否预约过此时间
        ReservationVo reservationVo = customerReservationMapper.getTimeByMobileAndTime(reservationDto.getMobile(),reservationDto.getTime());
        if (ObjectUtil.isNotEmpty(reservationVo)) {
            // 此手机号已预约该时间
            throw new BaseException(BasicEnum.PHONE_RESERVATION_TIME_EXIST);
        }


        Reservation reservation = BeanUtil.toBean(reservationDto, Reservation.class);
        reservation.setStatus(0);

        try {
            customerReservationMapper.save(reservation);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.SYSYTEM_FAIL);
        }
    }

    /**
     * 分页查询预约
     * @param pageNum
     * @param pageSize
     * @param status
     * @return
     */
    @Override
    public PageResponse<ReservationVo> list(Integer pageNum, Integer pageSize, Integer status) {
        PageHelper.startPage(pageNum,pageSize);

        // 获取userId
        Long userId = UserThreadLocal.get();
        // 分页查询
        Page<ReservationVo> resultPage = customerReservationMapper.list(status,userId);
        // 调用方法进行手机号脱敏
        Page<ReservationVo> page = handleMobile(resultPage);

        PageResponse<ReservationVo> pageResponse = new PageResponse<>(page);
        pageResponse.setRecords(page.getResult());

        return pageResponse;
    }

    /**
     * 取消预约
     * @param id
     */
    @Override
    public void cancel(Long id) {
        customerReservationMapper.update(id);
    }

    /**
     * 生成存储预约时间的可预约次数列表。
     *
     * @param time 基准时间（毫秒数）
     * @return 可预约的时间段列表
     */
    private List<ReservationCountVo> getTimeList(Long time) {
        // 定义LocalDateTime的格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        List<ReservationCountVo> timeList = new ArrayList<>();
        // 可预约时间段的开始时间
        Long reservationTime = time + START_TIME;

        // 循环生成每个时间段的可预约次数，直到达到最大数量限制
        while (timeList.size() <= TIME_LIST_MAX_SIZE -1) {
            String startTime = simpleDateFormat.format(reservationTime);
            // 将startTime转为LocalDateTime
            LocalDateTime parse = LocalDateTime.parse(startTime,formatter);
            ReservationCountVo reservationCountVo = new ReservationCountVo(parse, RSERVATION_MAX_COUNT);
            timeList.add(reservationCountVo);
            reservationTime += 1800000L; // 每个时间段间隔30分钟
        }
        return timeList;
    }

    /**
     * 数据脱敏
     * @param page
     * @return
     */
    private Page<ReservationVo> handleMobile(Page<ReservationVo> page) {
        // 数据脱敏
        for (ReservationVo reservationVo : page.getResult()) {
            String newMobile ="";
            String mobile = reservationVo.getMobile();
            String[] split = mobile.split("");

            for (int i = 0; i < split.length; i++) {
                String s = split[i];
                // 判断如果遍历到号码的第5,6,7位时,对号码进行处理
                switch (i) {case 3 : case 4 : case 5 : case 6 : s = "*";}
                // 拼接手机号
                newMobile += s;
            }
            // 设置新手机号
            reservationVo.setMobile(newMobile);
        }
        return page;
    }
}